<template>
  <view :id="$sUid" class="s-waterfall" :class="custom_class" :style="custom_style">
    <view v-for="item of columnList" :key="item.index" class="s-waterfall__column" :style="columnStyleList[item.index]">
      <slot :scopeParams="scopeParams" :list="item.list" :index="item.index" />
    </view>
  </view>
</template>

<script>
import componentMixin from '../../mixins/componentMixin';
import getComponentOptions from '../../common/getComponentOptions';
/**
 * s-waterfall 瀑布流
 * @description 瀑布流，自动分发各列数据，实现错位排列
 * @property {Number|String} column 列数
 * @property {Number|String} gutter 间距
 * @property {Number|String} loadTime 每个item加载时间
 * @property {Function} loadItem (item,callback) 自定义加载每个item，优先级高于loadTime，使用callback触发价值完毕
 * @example <s-waterfall ref="waterfall"></s-waterfall>
 */
export default {
  name: 'SWaterfall',
  mixins: [componentMixin],
  options: getComponentOptions({ virtualHost: false }),
  props: {
    column: {
      type: [Number, String],
      default: 2,
    },
    gutter: {
      type: [Number, String],
      default: 20,
    },
    loadTime: {
      type: [Number, String],
      default: 0,
    },
    loadItem: Function,
  },
  data: () => ({
    columnList: [],
  }),
  computed: {
    columnStyleList() {
      return this.columnList.map(({ index }) => this.$mergeStyle({
        marginLeft: index > 0 ? this.$addUnit(this.gutter) : '',
      }));
    },
  },
  watch: {
    column() {
      this.init();
    },
  },
  created() {
    this.list = [];
    this.resetId = 0;
    this.timer = null;
    this.init();
  },
  beforeDestroy() {
    this.clearTimer();
  },
  methods: {
    init() {
      const columnList = [];
      const column = parseInt(this.column);
      const data = [...this.list];
      for (let i = 0; i < column; i++) {
        columnList.push({ index: i, list: [] });
      }
      this.columnList = columnList;
      this.reset();
      this.push(data);
    },
    reset() {
      this.list = [];
      this.columnList.forEach(item => (item.list = []));
      this.clearTimer();
      this.resetId++;
      this.promise = Promise.resolve();
    },
    push(data) {
      if (!this._isMounted || this._isDestroyed || !this.columnList.length) return;
      const resetId = this.resetId;
      const loadTime = parseInt(this.loadTime);
      const loadItem = this.$getPropsFn('loadItem');
      this.list.push(...data);
      data.forEach(item => {
        this.promise = this.promise.then(() => new Promise(resolve => {
          if (resetId === this.resetId) {
            this.$getRect(`#${this.$sUid} .s-waterfall__column`, true).then(rects => {
              if (resetId === this.resetId) {
                const heights = rects.map(item => item.height);
                const index = heights.indexOf(Math.min(...heights));
                this.columnList[index].list.push(item);
                if (loadItem) {
                  loadItem(item, resolve);
                } else if (loadTime > 0) {
                  this.timer = setTimeout(resolve, loadTime);
                } else {
                  resolve();
                }
              } else {
                resolve();
              }
            });
          } else {
            resolve();
          }
        }));
      });
    },
    clearTimer() {
      if (this.timer) {
        clearTimeout(this.timer);
        this.timer = null;
      }
    },
  },
};
</script>

<style lang="scss" src="./index.scss"></style>
